package popple.display
{
	import flash.display3D.IndexBuffer3D;
	import flash.display3D.VertexBuffer3D;
	import flash.geom.Matrix3D;
	import flash.geom.Vector3D;
	import flash.utils.getQualifiedClassName;
	
	import popple.data.StaticData;

	/**
	 * 显示对象抽象类..
	 * @author popple
	 * 
	 */
	public class DisplayObject extends BaseObject
	{
		
		
	    public var matrix3d:Matrix3D=new Matrix3D;
		//父级
		protected var mParent:DisplayObjectContainer;
		//是否渲染
		protected var mDrawable:Boolean=true;
		
		//原始坐标系
		protected var mX:Number=0;
		protected var mY:Number=0;
		protected var mZ:Number=0;
		//计算后的坐标
		protected var mCalX:Number=0;
		protected var mCalY:Number=0;
		protected var mCalZ:Number=0;
		
		//原始大小
		protected var mWidth:Number=0;
		protected var mHeight:Number=0;
		protected var mLong:Number=0;
	
		//3D空间Z坐标，常用来排序
	    //public var zPos:Number;
		
		protected var mR:Number=0;
		protected var mG:Number=0;
		protected var mB:Number=0;
		protected var mA:Number=1;
		protected var mColor:uint;
		
		protected var mColors:Vector.<Number>=new Vector.<Number>(4);
		              //缩放比例
		protected var mScaleX:Number=1,
		              mScaleY:Number=1,
					  mScaleZ:Number=1,
					  //width,height产生的缩放
					  mAScaleX:Number=1,
					  mAScaleY:Number=1,
					  mAScaleZ:Number=1;
		
		
		
		//旋转角度
		protected var mRotX:int;
		protected var mRotY:int;
		protected var mRotZ:int;
		/**
		 *旋转轴 
		 */		
		protected var mPivot:Vector3D=new Vector3D(0,0,1);
		
		//贴图数据
		protected var mUVBuffer:VertexBuffer3D;
		//顶点数据
		protected var mVertexBuffer:VertexBuffer3D;
		//索引buffer
		protected var mIndexBuffer:IndexBuffer3D;

		//输出矩阵		
		protected var mWorldMatrix:Matrix3D=new Matrix3D;
		//初始化矩阵	
		protected var mInitiaM3D:Matrix3D=new Matrix3D;
		//缩放矩阵	
		protected var mScaleM3D:Matrix3D=new Matrix3D;
		//旋转矩阵		
		protected var mRotM3D:Matrix3D=new Matrix3D;
		//位移矩阵	
		protected var mCameraM3D:Matrix3D;
		protected var mTransM3D:Matrix3D=new Matrix3D;
		
		protected var mPosition:Vector3D=new Vector3D;
		public var stage:Stage;
		
		protected var mOrginWidth:Number=1,mOrginHeight:Number=1;
		public function DisplayObject()
		{
			abstractError();
			super();
			
			init();
		}
		private function abstractError():void
		{
			if (getQualifiedClassName(this) == "starling.display::DisplayObject")
			throw new Error("不能实例化抽象类DisplayObject");
		}
		
		private function init():void
		{
			this.x=mX;
			this.y=mY;
			this.z=mZ;
			this.color=0xffffff;
			this.alpha=1;
		}
	
		public function set rotationX(value:Number):void
		{
			mRotX=value;
			updateRotation();
		}
		
		public function set rotationY(value:Number):void
		{
			mRotY=value;
			updateRotation();
		}
		
		public function set rotationZ(value:Number):void
		{
			mRotZ=value;
			updateRotation();
		}
		
		public function get rotationX():Number
		{
			return mRotX;
		}
		
		public function get rotationY():Number
		{
			return mRotY;
			
		}
		
		public function get rotationZ():Number
		{
			return mRotZ;
			
		}
		private function updateRotation():void
		{
			mRotM3D.identity();
			mRotM3D.appendRotation(360-mRotX,Vector3D.X_AXIS,mPivot);
			mRotM3D.appendRotation(360-mRotY,Vector3D.Y_AXIS,mPivot);
			mRotM3D.appendRotation(-mRotZ,Vector3D.Z_AXIS,mPivot);
		}
		public function set scaleX(value:Number):void
		{
			mScaleX=value;
			mScaleX==0?mScaleX=1:mScaleX;
			updateScale();
		}
		private function updateScale():void
		{
			mScaleM3D.identity();
			mScaleM3D.appendScale(mAScaleX,mAScaleY,mAScaleZ);
			mScaleM3D.appendScale(mScaleX,mScaleY,mScaleZ);
		}
		public function set scaleY(value:Number):void
		{
			mScaleY=value;
			mScaleY==0?mScaleY=1:mScaleY;
			updateScale();
		}
		
		public function set width(value:Number):void
		{
			mWidth=value;
			mAScaleX=(mWidth-mOrginWidth)/mOrginWidth+1;
			mAScaleX==0?mAScaleX=1:mAScaleX;
			updateScale();
		}
		
		public function set height(value:Number):void
		{
			mHeight=value;
			mAScaleY=(mHeight-mOrginHeight)/mOrginHeight+1;
			mAScaleY==0?mAScaleY=1:mAScaleY;
			updateScale();
		}
		
		public function get width():Number
		{
			return mWidth;
		}
		
		public function get height():Number
		{
			return mHeight;
		}
		/**
		 *设置旋转角度 
		 * @param value
		 * 
		 */		
		override public function render():void
		{
			super.render();
			
			preRender();
			draw();
			composeMatrix();
		}
		/**
		 *初始比例缩放计算 
		 * 
		 */		
		protected function initSize():void
		{
			var scaleW:Number=mOrginWidth/Stage.width;
			var scaleH:Number=scaleW*(mOrginHeight/mOrginWidth);
			mInitiaM3D.identity();
			mInitiaM3D.appendScale(scaleW,scaleH,1);
			
			mAScaleX=(mWidth-mOrginWidth)/mOrginWidth;
			mAScaleY=(mHeight-mOrginHeight)/mOrginHeight;
			mAScaleX<=0?mAScaleX=1:mAScaleX;
			mAScaleY<=0?mAScaleY=1:mAScaleY;
		}
		/**
		 *buffer创建 
		 * 
		 */		
		protected function initBuffers():void
		{
			//mUVBuffer=mRenderHelper.getVertexBuffer(StaticData.uv,2);
			mVertexBuffer=mRenderHelper.getVertexBuffer(StaticData.vertices,3);
			mIndexBuffer=mRenderHelper.getIndexBuffer(StaticData.indexs);
		}
		protected function draw():void
		{
			
		}
		/**
		 *预渲染 
		 * 
		 */		
	    protected function preRender():void
		{
			
		}
		protected function composeMatrix():void
		{
			mWorldMatrix.identity();
			
			
			//trace("渲染:",this.name);
            matrix3d.identity();
			matrix3d.append(mScaleM3D);
			matrix3d.append(mRotM3D);
			matrix3d.appendTranslation(mCalX,mCalY,mCalZ);
			
			if(this.parent!=null)
			{
				matrix3d.append(this.parent.matrix3d);
			}
			mWorldMatrix.append(mInitiaM3D);
			mWorldMatrix.append(matrix3d);
			
		}
		
		public function get alpha():Number
		{
			return mA;
		}
		
		public function set alpha(value:Number):void
		{
			mA=value;
			mColors[3]=mA;
		}
		public function get position():Vector3D
		{
			return mPosition;
		}
		public function set parent(value:DisplayObjectContainer):void
		{
			mParent=value;
		}
		public function get parent():DisplayObjectContainer
		{
			return mParent;
		}
		public function set color(value:uint):void
		{
			mColor=value;
			mR=(mColor>>16)/255;
			mG=(mColor>>8&0xff)/255;
			mB=(mColor&0xff)/255;
			mColors[0]=mR;
			mColors[1]=mG;
			mColors[2]=mB;
		}
		
		public function get color():uint
		{
			return mColor;
		}
		
		public function set x(value:Number):void
		{
			mX=value;
			mCalX=mX*2/Stage.width;
			mPosition.x=mCalX;
		}
		
		public function set y(value:Number):void
		{
			mY=value;
			mCalY=mY*-2/Stage.height;
			mCalY*=Stage.scale;
			mPosition.y=mCalY;
		}
		
		public function set z(value:Number):void
		{
			mZ=value;
			mCalZ=mZ/1000;
			mPosition.z=mCalZ;
		}
		
		public function get x():Number
		{
			return mX;
		}
		
		public function get y():Number
		{
			return mY;
		}
		
		public function get z():Number
		{
			return mZ;
		}
		
		public function set visible(value:Boolean):void
		{
			mDrawable=value;
			
		}	
	}
}